# https://gitee.com/yueyinqiu5990/tj12413601/blob/master/assignment1/question3/interpolations/lagrange.py
import typing

from question3.interpolation_method import InterpolationMethod1d


class LagrangeInterpolation(InterpolationMethod1d):
    def interpolate(
            self,
            points: typing.Iterable[tuple[float, float]]) \
            -> typing.Callable[[float], float]:
        points = list(points)
        if len(points) < 2:
            raise ValueError(f"Cannot do interpolation with {len(points)} point.")
        factors: list[float] = []
        for i, (point_k_x, factor) in enumerate(points):
            iter_of_points = iter(points)
            for _, (point_x, _) in zip(range(i), iter_of_points):
                factor /= (point_k_x - point_x)
            next(iter_of_points)
            for point_x, _ in iter_of_points:
                factor /= (point_k_x - point_x)
            factors.append(factor)

        def result_function(x: float):
            result = 0
            for r_i, (_, point_k_y) in enumerate(points):
                current = factors[r_i]
                r_iter_of_points = iter(points)
                for _, (r_point_x, _) in zip(range(r_i), r_iter_of_points):
                    current *= (x - r_point_x)
                next(r_iter_of_points)
                for r_point_x, _ in r_iter_of_points:
                    current *= (x - r_point_x)
                result += current
            return result

        return result_function
